package beanstao.util.store.presenter;

import java.util.HashMap;
import java.util.Map.Entry;

import net.sf.json.JSONArray;

import beanstao.util.Formula;
import beanstao.util.collections.Pair;
import beanstao.util.enums.operator.Comparison;
import beanstao.util.id.DId;
import beanstao.util.id.Id;
import beanstao.util.response.PD;
import beanstao.util.response.PDs;
import beanstao.util.store.IQD;
import beanstao.util.store.dal.DbDal;
import beanstao.util.store.database.Column;
import beanstao.util.store.database.Columns;
import beanstao.util.store.database.Where;
import beanstao.util.store.domainobject.Domain;
import beanstao.util.store.domainobject.fields.PublicField;

import com.google.common.collect.Maps;

public abstract class AbstractDataPresenter<T extends Domain> extends AbstractPresenter implements IPresenter
{
	protected abstract DbDal<T> getDal();

	@Override
	public PD all(IQD data)
	{
		return PDs.builder(this.getDal().selectAll());
	}

	@Override
	public PD page(IQD data)
	{
		return PDs.builder(this.dbAllForPage(data, this.getDal()));
	}

	@Override
	public PD create(IQD data)
	{
		T domain = this.getDal().newBlankDomain();
		domain.fromRequest(data);
		return PDs.builder(this.getDal().create(domain));
	}

	@Override
	public PD delete(IQD data)
	{
		T domain = this.getDal().newBlankDomain();
		domain.fromRequest(data);
		return PDs.builder(this.getDal().delete(domain));
	}

	public PD exists(IQD data)
	{
		T domain = this.getDal().newBlankDomain();
		domain.fromRequest(data);
		return PDs.builder(this.getDal().exists(domain));
	}

	@Override
	public PD idName(IQD data)
	{
		Id id = DId.ME(data.get(PublicField.ID).$V().toString());
		PD data2 = PDs.builder(this.getDal().select(id));
		Domain domain = (Domain) data2.$Data();
		return PDs.builder(domain.get("name"));
	}

	@Override
	public PD idNameOfAll(IQD data)
	{
		Column fields = new Column();
		fields.append(new Formula("name"));
		Columns sqlList = Columns.ME(fields);
		return PDs.builder(this.getDal().select(sqlList, null));
	}

	@Override
	public PD idOfAll(IQD data)
	{
		// 创建sqlselectcolumn
		Column fields = new Column();
		fields.append(new Formula("id"));
		Columns sqlList = Columns.ME(fields);
		return PDs.builder(this.getDal().select(sqlList, null));
	}

	@Override
	public PD remove(IQD data)
	{
		T domain = this.getDal().newBlankDomain();
		domain.fromRequest(data);
		return PDs.builder(this.getDal().remove(domain));
	}

	@Override
	public PD removeByWhere(IQD data)
	{
		Where sqlText = data.toSimpleWhere();
		return PDs.builder(this.getDal().remove(null, sqlText));
	}

	@Override
	public PD removeAll(IQD data)
	{
		return PDs.builder(this.getDal().removeAll(DId.ME("system")));
	}

	@Override
	public PD count()
	{
		return PDs.builder(this.getDal().count(null));
	}

	@Override
	public PD count(IQD data)
	{
		return PDs.builder(this.getDal().count(data.toSimpleWhere()));
	}

	@Override
	public PD single(IQD data)
	{
		Id id = DId.ME(data.get(PublicField.ID).$V().toString());
		return PDs.builder(this.getDal().select(id));
	}

	@Override
	public PD update(IQD data)
	{
		T domain = this.getDal().newBlankDomain();
		domain.fromRequest(data);
		return PDs.builder(this.getDal().update(domain));
	}

	@Override
	public PD updateByWhere(IQD data)
	{
		T domain = this.getDal().newBlankDomain();
		domain.fromRequest(data);
		HashMap<String, Object> map = Maps.newHashMap();
		for (Entry<String, Object> domaEntry : domain.entrySet())
		{
			map.put(domaEntry.getKey(), domaEntry.getValue());
		}
		Where sqlText = data.toSimpleWhere();
		return PDs.builder(this.getDal().update(null, map, sqlText));
	}

	@Override
	public PD where(IQD data)
	{
		Where sqlText = data.toSimpleWhere();
		return PDs.builder(this.getDal().select(Columns.ME_ALL(), sqlText));
	}

	public PD wherePro(IQD data)
	{
		Where sqlText = data.toSimpleWhere();
		this.orderby(data, sqlText);
		this.groupby(data, sqlText);
		// 查询语句查询时列名的数组集合
		if (data.getKeys().contains("columns"))
		{
			JSONArray list = JSONArray.fromObject(data.get("columns").$V());
			Columns columns = Columns.ME_ALL();
			columns.clear();
			for (Object object : list)
			{
				Column selectField = new Column();
				selectField.append(new Formula(object.toString()));
				columns.add(selectField);
			}
			return PDs.builder(this.getDal().select(columns, sqlText));
		}
		return PDs.builder(this.getDal().select(Columns.ME_ALL(), sqlText));
	}

	public PD top(IQD data)
	{
		Where sqlText = data.toSimpleWhere();
		this.orderby(data, sqlText);
		this.groupby(data, sqlText);
		Pair<Integer, Integer> pair = this.limit(data);
		return PDs.builder(this.getDal().select(Columns.ME_ALL(), sqlText, pair.getLeft(), pair.getRight()));
	}

	@Override
	public PD like(IQD data)
	{
		// 创建sqlselectcolumn
		Columns sqlList = Columns.ME_ALL();

		// 添加Where条件
		Where where = Where.ME();
		for (String key : data.getKeys())
			where.and(key, Comparison.Like, "%" + data.get(key).$V() + "%");// 如果模糊查询存在or关系？？？jert

		return PDs.builder(this.getDal().select(sqlList, where));
	}
}
